#pragma once
#include "gp_EulerSequence.h"
#include "gp_Vec.h"

class gp_Vec;
class gp_Mat;


//! Represents operation of rotation in 3d space as queternion <br>
//!          and implements operations with rotations basing on <br>
//!          quaternion mathematics. <br>
//! <br>
//!          In addition, provides methods for conversion to and from other <br>
//!          representatons of rotation (3*3 matrix, vector and <br>
//!          angle, Euler angles) <br>
class gp_Quaternion  {
public:

  

  //! Creates an identity quaternion <br>
      gp_Quaternion();
  //! Creates quaternion directly from component values <br>
     gp_Quaternion(const double x,const double y,const double z,const double w);
  //! Creates copy of another quaternion <br>
     gp_Quaternion(const gp_Quaternion& theToCopy);
  //! Creates quaternion representing shortest-arc rotation <br>
//!          operator producing vector theVecTo from vector theVecFrom. <br>
     gp_Quaternion(const gp_Vec& theVecFrom,const gp_Vec& theVecTo);
  //! Creates quaternion representing shortest-arc rotation <br>
//!          operator producing vector theVecTo from vector theVecFrom. <br>
//!          Additional vector theHelpCrossVec defines preferred direction for <br>
//!          rotation and is used when theVecTo and theVecFrom are directed <br>
//!          oppositely. <br>
     gp_Quaternion(const gp_Vec& theVecFrom,const gp_Vec& theVecTo,const gp_Vec& theHelpCrossVec);
  //! Creates quaternion representing rotation on angle <br>
//!          theAngle around vector theAxis <br>
     gp_Quaternion(const gp_Vec& theAxis,const double theAngle);
  //! Creates quaternion from rotation matrix 3*3 <br>
//!          (which should be orthonormal skew-symmetric matrix) <br>
     gp_Quaternion(const gp_Mat& theMat);
  //! Simple equal test without precision <br>
       bool IsEqual(const gp_Quaternion& theOther) const;
  //! Sets quaternion to shortest-arc rotation producing <br>
//!          vector theVecTo from vector theVecFrom. <br>
//!          If vectors theVecFrom and theVecTo are opposite then rotation <br>
//!          axis is computed as theVecFrom ^ (1,0,0) or theVecFrom ^ (0,0,1). <br>
       void SetRotation(const gp_Vec& theVecFrom,const gp_Vec& theVecTo) ;
  //! Sets quaternion to shortest-arc rotation producing <br>
//!          vector theVecTo from vector theVecFrom. <br>
//!          If vectors theVecFrom and theVecTo are opposite then rotation <br>
//!          axis is computed as theVecFrom ^ theHelpCrossVec. <br>
       void SetRotation(const gp_Vec& theVecFrom,const gp_Vec& theVecTo,const gp_Vec& theHelpCrossVec) ;
  //! Create a unit quaternion from Axis+Angle representation <br>
       void SetVectorAndAngle(const gp_Vec& theAxis,const double theAngle) ;
  //! Convert a quaternion to Axis+Angle representation, <br>
//!          preserve the axis direction and angle from -PI to +PI <br>
       void GetVectorAndAngle(gp_Vec& theAxis,double& theAngle) const;
  //! Create a unit quaternion by rotation matrix <br>
//!          matrix must contain only rotation (not scale or shear) <br>
//! <br>
//!          For numerical stability we find first the greatest component of quaternion <br>
//!          and than search others from this one <br>
       void SetMatrix(const gp_Mat& theMat) ;
  //! Returns rotation operation as 3*3 matrix <br>
       gp_Mat GetMatrix() const;
  //! Create a unit quaternion representing rotation defined <br>
//!          by generalized Euler angles <br>
       void SetEulerAngles(const gp_EulerSequence theOrder,const double theAlpha,const double theBeta,const double theGamma) ;
  //! Returns Euler angles describing current rotation <br>
       void GetEulerAngles(const gp_EulerSequence theOrder,double& theAlpha,double& theBeta,double& theGamma) const;
  
       void Set(const double x,const double y,const double z,const double w) ;
  
       void Set(const gp_Quaternion& theQuaternion) ;
  
       double X() const;
  
       double Y() const;
  
       double Z() const;
  
       double W() const;
  //! Make identity quaternion (zero-rotation) <br>
       void SetIdent() ;
  //! Reverse direction of rotation (conjugate quaternion) <br>
       void Reverse() ;
  //! Return rotation with reversed direction (conjugated quaternion) <br>
       gp_Quaternion Reversed() const;
  //! Inverts quaternion (both rotation direction and norm) <br>
       void Invert() ;
  //! Return inversed quaternion q^-1 <br>
       gp_Quaternion Inverted() const;
  //! Returns square norm of quaternion <br>
       double SquareNorm() const;
  //! Returns norm of quaternion <br>
       double Norm() const;
  //! Scale all components by quaternion by theScale; note that <br>
//!          rotation is not changed by this operation (except 0-scaling) <br>
       void Scale(const double theScale) ;
    void operator *=(const double theScale) 
{
  Scale(theScale);
}
  //! Returns scaled quaternion <br>
       gp_Quaternion Scaled(const double theScale) const;
    gp_Quaternion operator *(const double theScale) const
{
  return Scaled(theScale);
}
  //! Stabilize quaternion length within 1 - 1/4. <br>
//!          This operation is a lot faster than normalization <br>
//!          and preserve length goes to 0 or infinity <br>
       void StabilizeLength() ;
  //! Scale quaternion that its norm goes to 1. <br>
//!          The appearing of 0 magnitude or near is a error, <br>
//!          so we can be sure that can divide by magnitude <br>
       void Normalize() ;
  //! Returns quaternion scaled so that its norm goes to 1. <br>
       gp_Quaternion Normalized() const;
  //! Returns quaternion with all components negated. <br>
//!          Note that this operation does not affect neither <br>
//!          rotation operator defined by quaternion nor its norm. <br>
       gp_Quaternion Negated() const;
    gp_Quaternion operator -() const
{
  return Negated();
}
  //! Makes sum of quaternion components; result is "rotations mix" <br>
       gp_Quaternion Added(const gp_Quaternion& theOther) const;
    gp_Quaternion operator +(const gp_Quaternion& theOther) const
{
  return Added(theOther);
}
  //! Makes difference of quaternion components; result is "rotations mix" <br>
       gp_Quaternion Subtracted(const gp_Quaternion& theOther) const;
    gp_Quaternion operator -(const gp_Quaternion& theOther) const
{
  return Subtracted(theOther);
}
  //! Multiply function - work the same as Matrices multiplying. <br>
//!          qq' = (cross(v,v') + wv' + w'v, ww' - dot(v,v')) <br>
//!          Result is rotation combination: q' than q (here q=this, q'=theQ). <br>
//!          Notices than: <br>
//!          qq' != q'q; <br>
//!          qq^-1 = q; <br>
       gp_Quaternion Multiplied(const gp_Quaternion& theOther) const;
    gp_Quaternion operator *(const gp_Quaternion& theOther) const
{
  return Multiplied(theOther);
}
  //! Adds componnets of other quaternion; result is "rotations mix" <br>
       void Add(const gp_Quaternion& theOther) ;
    void operator +=(const gp_Quaternion& theOther) 
{
  Add(theOther);
}
  //! Subtracts componnets of other quaternion; result is "rotations mix" <br>
       void Subtract(const gp_Quaternion& theOther) ;
    void operator -=(const gp_Quaternion& theOther) 
{
  Subtract(theOther);
}
  //! Adds rotation by multiplication <br>
       void Multiply(const gp_Quaternion& theOther) ;
    void operator *=(const gp_Quaternion& theOther) 
{
  Multiply(theOther);
}
  //! Computes inner product / scalar product / Dot <br>
       double Dot(const gp_Quaternion& theOther) const;
  //! Return rotation angle from -PI to PI <br>
       double GetRotationAngle() const;
  //! Rotates vector by quaternion as rotation operator <br>
       gp_Vec Multiply(const gp_Vec& theVec) const;
    gp_Vec operator *(const gp_Vec& theVec) const
{
  return Multiply(theVec);
}





protected:





private:



double x;
double y;
double z;
double w;


};






// other  functions and methods (like "C++: function call" methods)



